package com.x2.core.util;

import java.lang.reflect.Array;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * List工具类
 *
 * @author liubq
 * @since 20170711
 */
public class ListUtil {

    /**
     * 排序
     *
     * @param list       目标对象
     * @param comparator 排序
     */
    public static <T> void sort(final List<T> list, Comparator<T> comparator) {
        if (list == null || list.size() == 0) {
            return;
        }
        Collections.sort(list, comparator);
    }


    /**
     * 过滤出属性
     *
     * @param list   目标对象
     * @param keyFun key获取方法
     * @return 非空对象
     */
    public static <T, V> Set<T> filterSet(final Collection<V> list, Function<? super V, ? extends T> keyFun) {
        List<T> dataList = filterList(list, keyFun, null);
        return new HashSet<>(dataList);
    }


    /**
     * 过滤出属性
     *
     * @param list      目标对象
     * @param keyFun    key获取方法
     * @param predicate 条件方法
     * @return 非空对象
     */
    public static <T, V> List<T> filterSet(final Collection<V> list, Function<? super V, ? extends T> keyFun, Predicate<? super V> predicate) {
        List<T> dataList = filterList(list, keyFun, predicate);
        //set内部用map实现，所以不能用hashSet，下面代码是为了保存顺序
        List<T> newDataList = new ArrayList<>();
        for (T t : dataList) {
            if (!newDataList.contains(t)) {
                newDataList.add(t);
            }
        }
        return newDataList;
    }

    /**
     * 过滤出属性
     *
     * @param list   目标对象
     * @param keyFun key获取方法
     * @return 非空对象
     */
    public static <T, V> List<T> filterList(final Collection<V> list, Function<? super V, ? extends T> keyFun) {
        return filterList(list, keyFun, null);
    }

    /**
     * 过滤出属性
     *
     * @param list      目标对象
     * @param keyFun    key获取方法
     * @param predicate 条件方法
     * @return 非空对象
     */
    public static <T, V> List<T> filterList(final Collection<V> list, Function<? super V, ? extends T> keyFun, Predicate<? super V> predicate) {
        List<T> dataList = new ArrayList<T>();
        if (list == null || list.size() == 0) {
            return dataList;
        }
        T keyValue;
        boolean cond;
        for (V item : list) {
            cond = true;
            try {
                if (predicate != null) {
                    cond = predicate.test(item);
                }
                if (cond) {
                    keyValue = keyFun.apply(item);
                    if (keyValue != null) {
                        dataList.add(keyValue);
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return dataList;
    }

    /**
     * 字符串变数组
     *
     * @param ids
     * @return 非空对象
     */
    public static Long[] toLongArr(String ids) {
        if (ids == null || ids.trim().length() == 0) {
            return new Long[0];
        }
        String tempIds = ids.trim();
        String[] idList = tempIds.split(",");
        Long[] idArr = new Long[idList.length];
        int i = 0;
        for (String id : idList) {
            if (id != null && id.trim().length() > 0) {
                idArr[i++] = Long.valueOf(id.trim());
            }

        }
        return idArr;
    }

    /**
     * 字符串变数组
     *
     * @param ids
     * @return 非空对象
     */
    public static String[] toStringArr(String ids) {
        if (ids == null || ids.trim().length() == 0) {
            return new String[0];
        }
        String tempIds = ids.trim();
        String[] idList = tempIds.split(",");
        String[] idArr = new String[idList.length];
        int i = 0;
        for (String id : idList) {
            if (id != null && id.trim().length() > 0) {
                idArr[i++] = id.trim();
            }

        }
        return idArr;
    }

    /**
     * 字符串变List
     *
     * @param ids
     * @return 非空对象
     */
    public static List<Long> toLongList(String ids) {
        List<Long> newIdList = new ArrayList<>();
        if (ids == null || ids.trim().length() == 0) {
            return newIdList;
        }
        String tempIds = ids.trim();
        String[] idList = tempIds.split(",");

        for (String id : idList) {
            if (id != null && id.trim().length() > 0) {
                newIdList.add(Long.valueOf(id.trim()));
            }

        }
        return newIdList;
    }

    /**
     * 字符串变List
     *
     * @param ids
     * @return 非空对象
     */
    public static List<String> toStringList(String ids) {
        List<String> newIdList = new ArrayList<>();
        if (ids == null || ids.trim().length() == 0) {
            return newIdList;
        }
        String tempIds = ids.trim();
        String[] idList = tempIds.split(",");

        for (String id : idList) {
            if (id != null && id.trim().length() > 0) {
                newIdList.add(id.trim());
            }

        }
        return newIdList;
    }


    /**
     * 数组变成List
     *
     * @param datas
     * @return 非空对象
     */
    public static <T> List<T> toList(T... datas) {
        List<T> dataList = new ArrayList<>();
        if (datas == null) {
            return dataList;
        }

        for (T data : datas) {
            dataList.add(data);
        }
        return dataList;
    }

    /**
     * List变成数组
     *
     * @param datas
     * @return 对象(可能为空)
     */
    public static <T> T[] toArray(List<T> datas) {
        if (datas == null) {
            return null;
        }
        T[] newDatas = (T[]) Array.newInstance(datas.get(0).getClass(), datas.size());
        for (int i = 0; i < datas.size(); i++) {
            newDatas[i] = datas.get(i);
        }
        return newDatas;
    }


    /**
     * join
     *
     * @param dataList
     * @return 非空对象
     */
    public static <T> String join(Collection<T> dataList) {
        return join(dataList, ",");
    }


    /**
     * join
     *
     * @param dataList
     * @return 非空对象
     */
    public static <T> String join(Collection<T> dataList, String defaultChar) {

        if (dataList == null || dataList.size() == 0) {
            return "";
        }
        String tempChar = defaultChar;
        if (tempChar == null) {
            tempChar = ",";
        }
        StringBuilder s = new StringBuilder();
        for (T item : dataList) {
            s.append(tempChar).append(item);
        }
        return s.substring(tempChar.length());
    }

    /**
     * 分组
     *
     * @param list 目标对象
     * @return 非空对象
     */
    @SuppressWarnings("unchecked")
    public static <T, V> Map<T, V> map(final Collection<V> list, Function<? super V, ? extends T> keyFun) {
        Map<T, V> dataMap = new HashMap<T, V>();
        if (list == null || list.size() == 0) {
            return dataMap;
        }
        Object keyValue;
        for (V item : list) {
            try {
                keyValue = keyFun.apply(item);
                dataMap.put((T) keyValue, item);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return dataMap;
    }


    /**
     * 分组
     *
     * @param list 目标对象
     * @return 非空对象
     */
    @SuppressWarnings("unchecked")
    public static <T, V> MapList<T, V> mapList(final Collection<V> list, Function<? super V, ? extends T> keyFun) {
        MapList<T, V> dataMap = new MapList<T, V>();
        if (list == null || list.size() == 0) {
            return dataMap;
        }
        Object keyValue;
        for (V item : list) {
            try {
                keyValue = keyFun.apply(item);
                dataMap.put((T) keyValue, item);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return dataMap;
    }


    /**
     * 数据（列表）拆分，按照指定大小
     *
     * @param datas 数据
     * @param size  等分每组大小
     * @return 非空对象 拆分后集合
     */
    public static <T> List<List<T>> split(List<T> datas, int size) {
        return split(datas, size, size);
    }

    /**
     * 数据（列表）拆分，按照指定大小
     *
     * @param datas     数据
     * @param firstSize 第一组大小
     * @param size      以后各组大小
     * @return 非空对象 拆分后集合
     */
    public static <T> List<List<T>> split(List<T> datas, int firstSize, int size) {
        List<List<T>> resList = new ArrayList<List<T>>();
        if (datas == null || datas.size() == 0) {
            return resList;
        }
        boolean begin = true;
        List<T> rowList = new ArrayList<T>();
        for (int i = 0; i < datas.size(); i++) {
            if (begin) {
                if (rowList.size() == firstSize) {
                    resList.add(rowList);
                    rowList = new ArrayList<T>();
                    begin = false;
                }
            } else {
                if (rowList.size() == size) {
                    resList.add(rowList);
                    rowList = new ArrayList<T>();
                }
            }
            rowList.add(datas.get(i));
        }
        if (rowList.size() > 0) {
            resList.add(rowList);
        }
        return resList;
    }

}
